/**
//文档生成日期：2005.10.07
//
//(1)概述：
//类名称：Settings.java
//类说明：
//??	?? 利用J2ME的RMS存储读取数据的接口.
* 
//所在子系统：RssOwlMIDlet
//
//系统总描述:
	    我们提供的RSS无线阅读器J2ME版本[开源]是一个可以下载到手机(例如Nokia7610)或者其他无线手持设备(例如PocketPC)的应用程序，用来阅读存在于Internet中广泛的RSS新闻源。

	 子系统描述：
		RSS无线阅读器的功能列表：
	RSS Feed列表
		添加Rss Feed
		编辑Rss Feed
		删除Rss Feed
	读取Rss Feed新闻
		查看新闻摘要
		重新读取Rss Feed新闻
	关于我


//(2)历史记录:
//创建人: Tommi Laukkanen
//修改人: 郑昀(2005.10.07)
//联系我: Google Talk >> zhengyun@gmail.com
//Blogs:    http://blog.csdn.net/zhengyun_ustc/以及http://www.cnblogs.com/zhengyun_ustc

//(3)版权声明:
//由于我这个版本的RSS J2ME阅读器也是基于Tommi和garrey源代码基础上改编而来的，
//所以决定遵照GPL协议的大意开放源代码，您可以自由传播和修改，在遵照GPL协议的约束条件的前提下。

//(4)相关资源:
1：《[J2ME]RSSOwlMidlet(RSS无线阅读器)开源说明》
2：《[J2ME]RSSOwlMidlet(RSS无线阅读器)设计说明》
3：下载源代码：

////////////////////////////////////////////////////////////////////*/

package com.zemo.tools;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import javax.microedition.midlet.MIDlet;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

import com.zemo.control.GUIController;
import com.zemo.model.RssFeed;

/**********************************************************
//Settings
//
//Class Description:
 * 封装了对Rss Feeds在RMS中存取的操作.
 * 总的来说，改变还是比较大的，??	原来Tommi将Feed列表以及URL存储在RMS的一个条目，
 * 我放弃了这种做法，而是像garrey处理电话记录一样.
**********************************************************/
public class Settings {
    private static Settings 	 m_settings;
    private MIDlet          	 m_midlet;
	private static RecordStore m_store;
    private boolean         	 m_valuesChanged = false;
	private GUIController 		 controller;
	
	public Settings(GUIController control,
			MIDlet midlet)
	throws IOException, RecordStoreException{
		System.out.println("!-- Settings another Constructor --!\n");
		controller 	= control;
		m_midlet 	= midlet;
        openStore();
	}
    
    /**
     * Singleton pattern is used to return 
     * only one instance of record store
     */
    public static synchronized Settings getInstance( GUIController control,
			MIDlet midlet )
    throws IOException, RecordStoreException {
        if( m_settings == null ) {
			System.out.println("!-- Settings::getInstance --!\n");
			m_settings = new Settings( control, midlet );
        }
        return m_settings;
    }

    /** Constructor */
    private Settings( MIDlet midlet )
    throws IOException, RecordStoreException {
		System.out.println("!-- Settings default Constructor --!\n");
        m_midlet = midlet;
		openStore();
    }
    
    /** Load properties from record store */
    private synchronized void openStore()
    throws IOException, RecordStoreException {
		
		System.out.println("!-- Begin load --!\n");
        
        m_valuesChanged = false;
        
        try {
			m_store = RecordStore.openRecordStore(SResources.RECORDSTORE_NAME, true );
            if( m_store.getNumRecords() == 0 ) {
				System.out.println("!-- 没有记录 --!\n");

				// 如果没有在记录中找到Rss Feed，我们就自己给记录中加入预定义的一些RssFeed
				DefaultRssFeeds();
            } else {
				System.out.println("!-- 找到了上次的记录 --!\n");
            }
        }  catch( Exception e ){}
    }
	
    // 关闭RecordStore
    public synchronized void closeStore() {
        if (m_store != null) {
            try {
				m_store.closeRecordStore();
				m_store = null;
            } catch (RecordStoreException ex) {}
        }
    }
	
	/**********************************************************
	//	 Settings::DefaultRssFeeds
	//
	//	 Description:
	//	  如果没有在记录中找到Rss Feed，我们就自己给记录中加入预定义的一些RssFeed
	//
	//	 Parameters:
	//	 Return Values:
	//   Remark:
	 * 		往RMS中实际存入预定义的Rss Feeds,这样在用户手机上一开始就有可供浏览的RSS源了
	//	 Author:
	//	      zhengyun@ultrapower 2005.10.07
	//
	**********************************************************/
	private void DefaultRssFeeds()
	throws IOException, RecordStoreException
	{
		System.out.println("!-- Enter DefaultRssFeeds --!");  
		byte[] dataInitRssFeed = 
			String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED1)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED2)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED3)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED4)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED5)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED6)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = String.valueOf(SResources.getChars(SResources.TXT_T_RSSFEED7)).getBytes();
		m_store.addRecord( dataInitRssFeed, 0, dataInitRssFeed.length );
		
		dataInitRssFeed = null;
	}
	
	/**********************************************************
	//	 Settings::addRssFeed
	//
	//	 Description:
	//	  向RMS中存储一条RssFeed
	//
	//	 Parameters:
	 * 		feed: 封装了feed的名称、URL的类实体
	//	 Return Values:
	 * 		int: 存储在RMS中的序号,可供以后找到这条记录
	**********************************************************/
    public int addRssFeed(RssFeed feed) {
                   
        try {
            byte[] data = feed.getStoreString().getBytes();
            int id  = m_store.getNextRecordID();
			System.out.println("!-- 添加记录:" + id); 
        	int rec = m_store.addRecord(data,0,data.length);
        	return id;
        } catch (RecordStoreException ex) { }
        
        return -1;
    }
	
	/**********************************************************
	//	 Settings::updateRssFeed
	//
	//	 Description:
	//	  在RMS找到指定的RssFeed并刷新它
	//
	//	 Parameters:
	 * 		feed: 封装了feed的名称、URL的类实体
	//	 Return Values:
	**********************************************************/
    public void updateRssFeed(RssFeed feed){

        try {
			int id = feed.getId();
			System.out.println("!-- 编辑记录:" + id);                  
            byte[] data = feed.getStoreString().getBytes();
			m_store.setRecord(id,data,0,data.length);
        	 
        } catch (RecordStoreException ex) { }
    }
    
	/**********************************************************
	//	 Settings::getRssFeed
	//
	//	 Description:
	// 		访问一条记录
	//
	//	 Parameters:
	 * 		id: feed在RMS中存储的序号
	//	 Return Values:
	 * 		RssFeed: 找到后,就返回这个Feed实体
	**********************************************************/
    public RssFeed getRssFeed(int id){
		RssFeed feed = null;

        try {
			System.out.println("!-- 访问记录:" + id);
        	feed = new RssFeed(id, m_store.getRecord(id));
        } catch (RecordStoreException ex) { }

         return feed;
    }
    
	/**********************************************************
	//	 Settings::deleteRssFeed
	//
	//	 Description:
	// 		删除一条记录
	//
	//	 Parameters:
	 * 		id: feed在RMS中存储的序号
	//	 Return Values:
	**********************************************************/
    public void deleteRssFeed(int id){
            try {
				System.out.println("!-- 删除记录:" + id);
            	m_store.deleteRecord(id);
            } catch (RecordStoreException ex) {}
    }

	/**********************************************************
	//	 Settings::getRssFeeds
	//
	//	 Description:
	// 		获取RMS中存储的所有的Feed列表
	//
	//	 Parameters:
	 * 		
	//	 Return Values:
	 * 		Vector: 包含了所有存储的Rss Feed列表
	//   Remark:
	 * 		首先枚举出指定Store中所有的记录,遍历每一条记录,如果是RssFeed,
	 * 		就将它插入到Vector中，最后返回这个包含了所有存储的Rss Feed。
	**********************************************************/
    public Vector getRssFeeds(){
		
		// 先重新加载
		/*try{
			openStore();
		}
		catch(Exception exc){}*/
		
        Vector bookmarks 		= new Vector(SResources.MAX_FEEDS);
        RecordEnumeration enums = null;
        int ind = 0;
        try{
            RssFeed feed = null;
			enums = m_store.enumerateRecords(null, new RssFeedComparator(), false);
			if(enums != null)
			{
	            while(enums.hasPreviousElement()){
	            	//ind  = enums.previousRecordId();
					
					// previousRecordId also advances the record pointer, so we have no
		            // need to call previousRecord() as well.
					ind  = enums.previousRecordId();
					
		            //Retrieve the data from the next record
		            //and make it the current record
		            //Set up a byte array buffer and some helper streams
		            byte[] rec = new byte[m_store.getRecordSize(ind)];
		            rec = m_store.getRecord(ind);
					System.out.println("本次遍历的id为:" + ind);
					
					if(rec != null)
					{
						try {
							feed = new RssFeed(ind, rec);
						}
			            catch (Exception e) {
			                // Debug
			                System.out.println("添加RssFeed时发生了异常:" + e.toString());
			            }
			            finally {
			               //Add the feed item to the Vector
							bookmarks.addElement(feed);
							System.out.println("本次遍历的feed为:\n+" + 
									feed.getName() + "+\n" + feed.getUrl());
							rec = null;
							feed = null;
			            }
					}
	            }
				System.out.println("!-- 记录枚举遍历完毕 --!");
			}
			else
			{
				System.out.println("!-- enums is null! --!");
			}
            
        }
		catch(Exception ex){ex.printStackTrace();}
        finally{
        		try{
					enums.destroy();
        		}catch(Exception e){}
        }//end finally
    
        return bookmarks;
    }
	

	/**********************************************************
	//	 Settings::RssFeedComparator
	//
	//	 Description:
    // 	一个简单的比较器
	// 	更详细信息参看
	// 	http://www.zdnet.com.cn/developer/code/story/0,2000081534,39068540,00.htm
	// 	<探索J2ME：对记录进行排序>
	//
	**********************************************************/
    private class RssFeedComparator implements RecordComparator{
       
		private ByteArrayInputStream stream;
	    private DataInputStream reader;

	    public int compare(byte[] bytes, byte[] bytes1) {
	        long d1 = 0, d2 = 0;

	        try {
	            // Compares records, sorts them
	            // in descending order

	            //Retrieve ExpenseDate from the first record
	            stream = new ByteArrayInputStream(bytes);
	            reader = new DataInputStream(stream);
	            //Get our date from the byte stream
	            //in "number of milliseconds in epoch" format
	            d1 = reader.readLong();

	            //Retrieve ExpenseDate from the second record
	            stream = new ByteArrayInputStream(bytes1);
	            reader = new DataInputStream(stream);
	            //Get our date from the byte stream
	            d2 = reader.readLong();
	        }
	        catch (Exception e) {
	            // Debug
	            System.out.println("RssFeedComparator Exception:" + e.toString());
	        }
	        finally {
	            if (d1 == d2) {
	                return RssFeedComparator.EQUIVALENT;
	            } else if (d1 > d2) {
	                return RssFeedComparator.PRECEDES;
	            } else {
	                return RssFeedComparator.FOLLOWS;
	            }
	        }
	    }
    }
}
